from config import *
from help import *
from gui_sub import *

#画坐标，点位，鼠标附近提示点，角度微调提示点
class my77(QMainWindow):
    def __init__(self):
        super().__init__()                     
        self.setWindowFlags(Qt.FramelessWindowHint|Qt.WindowStaysOnTopHint|Qt.ToolTip)                          
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setGeometry(0, 0, 0, 0)
        self.hide()            
        self.show()
        self.co = 0
        self.co2 = 0        
        t = QTimer(self)
        t.timeout.connect(self.ont)
        t.start(round(100/6))
        self.last = None
        self.zl = []
        self.showl = set()
        self.show_one_time = 0
        self.one_pos = (0, 0)
        cfg.w2showing = False            
        self.cir = wcir(False, True)
        self.cirsign = (0, )
        self.cur_pos=(0,0)
        
        self.lastRefreshTime = 0
        self.lastRefreshTimeDu = 0
        self.to_is_changing = False
        cfg.w2_last_ge = 0
        cfg.w2_last_to = 0
        cfg.w2_last_dis = 0            
        self.fix_c = wcir(False)
        self.sca_c = wcir(True)
        self.last_add1 = 0
        self.last_add2 = 0
        self.isNewPos = True
        self.last_cur_pos = (0,0)
        self.last_dxdy = (0,0)
        self.lastxy = (0, 0)
        self.zero_zi=wzi()
        self.is_scal = False

        self.er_l = []
        for i in range(er_zi_len):
            self.er_l.append(wzi())
        self.pos_zi = []
        for i in range(15):
            self.pos_zi.append(wzi())
        self.show_pos = False
        self.erzi2=wzi()
        self.erzi3=wzi()
        for i in range(max_zi):
            self.zl.append(wzi())

    def needRet(self):        
        if cfg.show_one_onetime:
            cfg.show_one_onetime = False
            return False
        
        if self.is_scal:
            return False
        
        if cal_dis(cfg.fix_pos,self.cur_pos) == 0:
            return False        
        
        if  cfg.force_show:            
            return False
            
        if cfg.mouse_mode==0 or  cfg.mouse_mode in mouse_checking_l:
            if self.to_is_changing:
                return False            
            return True
        
        if cfg.mouse_mode == 2:
            return False
        
        cfg.show_one_on = False
        return False        
    def cir_force(self,ff):
        if self.cir.f != ff:
            self.cir.f = ff
            self.cir.update()

    def draw_cir(self):
        from mpp import can_auto_to_man        
        x,y =  self.cur_pos
        mmx = time.time()-cfg.right_mouse_time<jump_qu_interval
        s = (cfg.isShow, cfg.show_one_on, cfg.w2showing, cfg.show_mouse_tip, x, y,mmx,cfg.show_ff,
             cfg.force_show, cfg.show_one_onetime, cfg.mouse_mode,cfg.min_ge,cfg.jump_state)
        if cfg.jump_state==0 and cfg.mouse_tip_no_show and cfg.mouse_track2_has_left and not \
                cfg.mouse_track2_on and not can_auto_to_man(time.time()+0.11,False):
            self.cir.draw(x+cir_para[0]+cir_para[4], y+cir_para[1]+cir_para[5])
            self.cir_force(True)
            return
        if cfg.jump_state==1 and cfg.keep_qu and cfg.keep_qu_dx<jump_qu_gap and \
            time.time()-cfg.right_mouse_time<jump_qu_interval and not cfg.mouse_track2_on:
            self.cir.draw(x+cir_para[0]+cir_para[4], y+cir_para[1]+cir_para[5])
            self.cir_force(True)
            return
        if cfg.show_ff:
            self.cir.draw(x+cir_para[0]+cir_para[4], y+cir_para[1]+cir_para[5])
            self.cir_force(True)
            return
        
        if self.cirsign == s:
            return
        
        self.cirsign = s
        if cfg.mouse_tip_no_show:
            ignr = (cfg.mouse_mode==4)
        else:
            ignr = (cfg.mouse_mode in (1,3,4))
        if is_no_move() and not cfg.force_show and cfg.mouse_mode not in (0,1):
            self.cir.dohide()    
        if cfg.isShow or (cfg.show_one_on and cfg.w2showing and cfg.show_mouse_tip):
            self.cir.draw(x+cir_para[0]+cir_para[4], y+cir_para[1]+cir_para[5])
            ff = cfg.force_show
            if self.cir.f != ff:
                self.cir.f = ff
                self.cir.update()
        elif cfg.mouse_mode < 0:
            self.cir.dohide()

        elif not cfg.isShow and cfg.show_one_on and not cfg.w2showing and \
            (cfg.show_mouse_tip or ignr or (cfg.force_show and (cfg.min_ge==0) and not cfg.force_tip_no_show ) ) and not cfg.show_one_onetime:
            if cfg.mouse_mode in( 3,):
                self.cir.draw(cfg.fix_pos[0], cfg.fix_pos[1])
                if not self.cir.f:
                    self.cir.f = True
                    self.cir.update()    
            elif cfg.mouse_mode in( 4,):
                self.cir.draw(cfg.mouse_m_dst_stop[0], cfg.mouse_m_dst_stop[1])
                if not self.cir.f:
                    self.cir.f = True
                    self.cir.update()    
            elif cfg.mouse_mode == 1:
                self.cir.draw(cfg.fix_pos[0], cfg.fix_pos[1])
                if  self.cir.f:
                    self.cir.f = False
                    self.cir.update()                
            else:
                self.cir.draw(x+cir_para[0], y+cir_para[1])
                if self.cir.f != cfg.force_show:
                    self.cir.f = cfg.force_show
                    self.cir.update()
        else:            
            self.cir.dohide()

    def cal_to(self):            
        if time.time()-cfg.to_change_time<to_lap or not self.isNewPos:
            return
        if self.to_is_changing:
            self.to_is_changing = False            
            cfg.w2_last_ge = cfg.last_ge
            cfg.w2_last_dis = cal_dis(getp(self.cur_pos), cfg.fix_pos)
            a = get_snap_sort()
            if not a:
                cfg.w2_last_to = 0
                cfg.w2_last_max_ge = 1
            else:
                cfg.w2_last_to = min(cfg.to+cfg.w2_last_dis, max(0,cfg.w2_last_dis*int(a[-1][0])-2))
                cfg.w2_last_max_ge = max(1,int(a[-1][0]))

            if cfg.w2_last_dis<min_d:
                cfg.w2_min_ge = math.ceil(cfg.w2_last_to/min_d)
            else:
                cfg.w2_min_ge = cfg.last_ge
            print('to not change',cfg.to,cfg.w2_last_to,cfg.w2_last_dis,cfg.w2_last_ge)

    def get_show_l(self):
        a = sorted(self.showl,key=lambda x: int(x[0]))
        sl = set()
        
        if len(a) == 0:
            return sl
        
        if int(a[0][0]) == 0:
            sl.add(a[0])
            a = a[1:]

        if len(a) < 2:
            cfg.far = a[-1]
            return self.showl
        
        d = cal_dis((a[0][1],a[0][2]),(a[1][1],a[1][2]) )
        if d == 0:
            cfg.far = a[-1]
            return self.showl
                    

        last_idx_cur = 0        
        for i in range(len(a)):
            if is_in_cur_screen(a[i][1], a[i][2]):
                last_idx_cur = i

        ne = get_near_count(d,last_idx_cur)        
        sl.update( a[0:ne])  

        last_idx = 0
        czi = int(float(cfg.sum))
        ne_d = 1000000
        dst_zi = -1

        for i in range(len(a)):
            if is_in_all_screen(a[i][1], a[i][2]):
                last_idx = i
                dd = abs(czi-int(a[i][0]))
                if dd<ne_d:
                    ne_d = dd
                    dst_zi = i        
        
        if czi>1 and dst_zi>0:
            xx = int(a[dst_zi][0])
            add_to_show_list(xx, dst_zi<last_idx)            

        for i in range(len(a)):
            if i>last_idx:
                break
            if int(a[i][0]) in cfg.add_show:                
                sl.add(a[i])            

        far1 = get_far_count(d,last_idx_cur,ne-1)
        far2 = get_far_count(d,last_idx,last_idx_cur)
        sl.update(a[ max(0, last_idx_cur+1-far1):last_idx_cur+1])
        sl.update(a[ max(0, last_idx+1-far2):last_idx+1])
                
        si, ei = add_idx(ne-1,last_idx_cur+1-far1, d,self.last_add1)
        self.last_add1 = si
        sl.update(a[si:si+ei])
           
        si2, ei2 = add_idx(last_idx_cur,last_idx+1-far2 , d,self.last_add2)
        self.last_add2 = si2
        sl.update(a[si2:si2+ei2])

        if  last_idx+1-far2>0 and a[last_idx-far2] not in sl:
            cfg.far = a[max(0, last_idx+1-far2)]
        else:
            cfg.far = a[-2]
        if cfg.show_mode_plus and ei>0:
            sl.update(a[si+ei:max(0, last_idx+1-far2)])
        if cfg.show_mode_plus and ei2>0:
            sl.update(a[si2+ei2:max(0, last_idx+1-far2)])

        return sl                
    def draw_er(self):
        co = 0
        for i in cfg.add_show2:
            a,zx,zy = get_er_pos(i)
            if not a:
                continue
            co +=1
            if co>er_zi_len:
                break
            self.er_l[co-1].draw(str(i),zx,zy,False)                    
        for i in range(co,er_zi_len):
            self.er_l[i].dohide()        

    def drawPos(self):
        if self.show_pos == cfg.show_pos:
            return
        self.show_pos = cfg.show_pos
        if not self.show_pos:
            for i in self.pos_zi:
                i.dohide()
            return
        co = -1
        for k,v in cfg.pos_m.items():
            co += 1
            if co>=15:
                return            
            ss = {'10':'.', '11':'+','13':'*','14':'/'}.get(str(k),'')
            sk = str(k)
            if ss:
                sk = ss+'(%s)'%sk
            self.pos_zi[co].draw(sk,v[0]+8,v[1],True)

    def ont(self):
        self.cur_pos = get_cur_pos()
        tt = time.time()
        if tt-cfg.last_move_time<0.003:
            time.sleep(0.003+cfg.last_move_time-tt)
            
        self.drawPos()
        self.is_scal = is_sca_delay()
        self.ont2()        
        if not cfg.w2showing and cfg.capsShow and cfg.sum[0]!='0':
            ff = int(float(cfg.sum))
            a,x,y = get_er_pos(ff)
            if not a:
                self.erzi3.dohide()
            else:
                self.erzi3.draw(str(ff),x,y,False)
        else:
            self.erzi3.dohide()

    def ont2(self):
        if cfg.jump_task!=None or cfg.move_task!=None:
            for i in range(max_zi):                
                self.zl[i].dohide()
            cfg.w2showing = False
            return

        if cfg.x2_mode:
            return
        check_mouse_mode()                
        self.draw_cir()     
        if cfg.x2_pressed and cfg.x2_type==1 and cfg.show_mode!=0 and not cfg.is_suo:
            return
        self.draw_er()         
        dd2 = cal_dis(getp(self.cur_pos),cfg.fix_pos)                
        ds = (cfg.min_ge==3 and cfg.getokuai!=100) or (cfg.min_ge==1 and cfg.getokuai)
        if time.time()-pm.scroll_re_time<0.1 and ds:
            return
        
        if cfg.min_ge!=0 and not cfg.min_ge_force_show and dd2>cfg.ge_wait_dis2 and not ds:
            cfg.min_ge_force_show = True
            print('ge force show')
            if not cfg.w2showing:                
                dotdot()

        cur = (0, 0)
        if cfg.isShow or cfg.show_one_on:
            cur = self.cur_pos
        
        sign =  (time.time()-cfg.x2_mode_exit_time>x2_delay2, cfg.capsShow, tuple(cfg.add_show2), cfg.show_mode, cfg.x2_pressed,cfg.is_suo,cfg.min_ge_force_not_show, cfg.min_ge_force_show,
                  cfg.min_ge,cfg.isShow, cfg.fix_pos, cur, cfg.sum,cfg.sca,cfg.show_mode_plus,
                  cfg.sca_du, cfg.sca_cur, cfg.sca_cur_pos, time.time()-cfg.to_change_time>to_lap,
                 cfg.show_one_on, cfg.to, cfg.showCut, cfg.fix_scroll,cfg.manu_add,tuple(cfg.add_show),cfg.sum)
        
        chk = True
        if cfg.w2showing:
            if not self.isNewPos or self.to_is_changing:
                chk = False

        if self.last == sign and not cfg.show_one_onetime and time.time() - cfg.to_time > 0.5 and chk and \
         time.time()-cfg.clear_time2>0.1:            
            return
        
        self.co2 += 1
        if  (cfg.fix_scroll == 0) and (cfg.manu_add==0) and not cfg.isShow and \
            cfg.show_one_on and not cfg.w2showing and self.needRet() and chk:            
            return                    
            
        if self.co2 % 100 == 0:
            print('co2', self.co2)

        self.last = sign
        self.showl = []
        self.fix_c_show = False
        self.sca_c_show = False       
        cfg.has_show_sca = False
        
        to_lock.acquire()        
        if time.time()-cfg.to_change_time<to_lap:            
            self.to_is_changing = True
        

        self.paintEvent2(1)        
        dd2 = cal_dis(getp(self.cur_pos),cfg.fix_pos)
        if cfg.min_ge!=0 and dd2>=min_d  and not cfg.min_ge_has_refresh and cfg.min_ge_force_show:
            print('ge refresh')
            cfg.min_ge_has_refresh = True
            self.to_is_changing = True
        self.cal_to()
        to_lock.release()

        
        
        if not self.fix_c_show:
            self.fix_c.dohide()
        if not self.sca_c_show:
            self.sca_c.dohide()
        
        cfg.w2snap =copy.deepcopy(self.showl)       
        def sortF(x):
            x = int(x[0])
            if x==0:
                return max_l
            return x

        showlSort = sorted(self.showl,key=sortF)  
           
        sl = self.get_show_l()
        maxi = 0
        for i in showlSort:
            st, x, y = i
            idx = int(st)
            if i in sl and idx > maxi:
                maxi = idx
        
        if abs(cfg.manu_add)==1 and not cfg.last_has_color:
            cfg.zi_no_color = maxi
        elif cfg.fix_scroll!=0 or cfg.manu_add!=0:
            cfg.zi_no_color = 0
        
        cfg.fix_scroll = 0
        cfg.manu_add = 0
        cfg.maxi = maxi        
        sh = False
        hasZero = False
        cfg.last_has_color = False
        cfg.draw_set=set()
        for i in range(max_zi):
            if i >= len(showlSort) or ( cfg.showCut and not cfg.isShow and showlSort[i] not in sl):
                self.zl[i].dohide()
            else:
                zi, x, y = showlSort[i] 
                sh = True               
                cfg.w2showing = True  
                cfg.w2showing_for_suo = True              
                cfg.force_show = False
                if  cfg.is_suo and cfg.x2_pressed and cfg.x2_type==0 and cfg.suo_dis<=1:
                    self.zl[i].dohide()
                    cfg.w2showing_for_suo = False
                elif i==0 and dd2<no_show_dis and cfg.min_ge!=0:
                    self.zl[i].dohide()
                elif int(zi) == maxi:
                    if (dd2*maxi>last_sign_size or cfg.isShow or len(cfg.add_show2)>0) \
                        and not (is_sca() and cfg.sca_noshow_last) and maxi!=cfg.zi_no_color:
                        self.zl[i].draw(zi, x, y, True)          
                        cfg.draw_set.add(zi) 
                        cfg.last_has_color = True         
                    else:
                        self.zl[i].draw(zi, x, y, False)
                        cfg.draw_set.add(zi)
                else:
                    if int(zi)==0:
                        hasZero = True
                        self.zero_zi.draw(zi, x, y, False)
                        cfg.draw_set.add(zi)
                        self.zl[i].dohide()                            
                    else:
                        self.zl[i].draw(zi, x, y, False)
                        cfg.draw_set.add(zi)
                    
                if not cfg.isShow and cfg.show_one_on:
                    self.one_pos = (x, y)
        cfg.w2showing = sh
        if not hasZero:
            self.zero_zi.dohide()
        if sh:
            cfg.show_one_onetime = False

        ff = int(float(cfg.sum))
        dr = False
        if cfg.capsShow:
            dr = True        

        if sh and ff>maxi and dr:                
            z,x,y = get_er_pos(ff)
            self.erzi2.draw(str(ff),x,y,False)
        else:
            self.erzi2.dohide()

    def chgFix(self):
        if is_sca():
            return        
        x,y = self.cur_pos
        cfg.fix_pos = (x-self.last_dxdy[0],y-self.last_dxdy[1]) 
      
    def get_xy_sca(self):
        x,y = getp(self.cur_pos)            
        x2, y2=  self.lastxy
        if time.time() - self.lastRefreshTimeDu<du_refresh_interval:
            return False,getp(self.cur_pos),(0,0),x2,y2        
        self.lastRefreshTimeDu = time.time()            
        d2 = cal_dis(cfg.fix_pos,(x2,y2))
        if d2==0:
            return False,getp(self.cur_pos),(0,0),x2,y2        
        du = math.atan2(y-cfg.fix_pos[1],x-cfg.fix_pos[0])
        return  False,getp(self.cur_pos),(0,0),cfg.fix_pos[0]+math.cos(du)*d2 ,cfg.fix_pos[1]+math.sin(du)*d2
    
    def get_xy(self):      # 是否使用cur,cursor_pos,dx,dy,x,y      
        if cfg.isShow or  time.time() - cfg.to_time > 0.3:
            if not self.isNewPos:
                self.chgFix()
                
            self.isNewPos = True
            x, y = getp(self.cur_pos)
            self.lastRefreshTime = time.time()           
            self.lastRefreshTimeDu = 0 
            return False,getp(self.cur_pos),(0,0), x, y
        
        if  time.time() - self.lastRefreshTime <len_refresh_interval:
            self.isNewPos = False
            if is_sca():
                return self.get_xy_sca()
            if time.time() - self.lastRefreshTimeDu<du_refresh_interval:                
                return True,self.last_cur_pos,self.last_dxdy,0,0
        
            x,y = getp(self.cur_pos, False)                                                
            self.lastRefreshTimeDu = time.time()      
            dx,dy = self.last_dxdy
            d2 = math.sqrt(dx*dx+dy*dy)                        
            du = math.atan2(y-cfg.fix_pos[1],x-cfg.fix_pos[0])
            cur_pos = self.cur_pos
            dx = math.cos(du)*d2
            dy = math.sin(du)*d2            
            return True,cur_pos,(dx,dy),0,0            
          
        x, y = getp(self.cur_pos, False)        
        self.lastRefreshTime = time.time()
        self.lastRefreshTimeDu = 0        
        return False,getp(self.cur_pos),(0,0),x, y                                

    def cal_ge(self, to):                          
        dx = min_d
        dy = 0
        ll = math.sqrt(dx*dx+dy*dy)
        
        step = max(1, math.ceil(min_d / ll))
        st = step
        min_idx = step
        for i in range(step,max_l, step):
            if i * ll > min_d_mouse:
                min_idx = i
                break              
        st = min_idx               
        rr =  range(st, max_l, step)
        l = []
        for i in rr:            
            zx = dx * i
            zy = dy * i
            l.append((str(i), zx, zy))            
            gg = 1
                
            if len(l) >= max_zi:
                break

            if len(l)>=gg and i*ll>to:
                break
                           
            if i * ll > max_l:
                break
        return len(l)
            
    def needBreak(self, i, ll, gg):
        if len(self.showl) < gg:
            return False
        
        if not self.is_scal:
            real_l = len(self.showl)
        else:
            real_l = len(self.showl) - 1        
        
        pos =  self.cur_pos
        if is_sca():
            pos = cfg.sca_start_pos
        pd = cal_dis(pos, cfg.fix_pos)
        gea,geb = get_ge(pd)
        if pd>ge_wait_dis and not cfg.min_ge_force_not_show:
            cfg.min_ge_force_show = True
        noShow = cfg.min_ge_force_not_show and not cfg.min_ge_force_show
        if not noShow and (pd>ge_wait_dis or cfg.min_ge_force_show) and ( i * ll <gea or real_l<geb):            
            return False
        
        if cfg.show_mode==0:
            if i>=cfg.w2_last_max_ge:
                return True
            return False
        
        if cfg.w2_last_dis >= min_d:            
            if pd > cfg.w2_last_dis:                
                if real_l >= cfg.w2_last_ge:
                    return True                                                    
            else:
                if i * ll >= cfg.w2_last_to:
                    return True
        else:          
            if pd < min_d :
                if i * ll >= cfg.w2_last_to:
                    return True
            else:
                if real_l >= cfg.w2_min_ge :
                    return True   
            
        return False
        
    def paintEvent2(self,e):        
        if not cfg.isShow and not cfg.show_one_on:
            return
        
        self.co += 1
        if self.co % 300 == 0:
            print('paintEvent1',self.co,time.monotonic())
            
        cur,cur_pos,dxdy,px, py = self.get_xy()        
        rdx,rdy = dxdy

        if cur:
            dx = rdx
            dy = rdy
            x = cur_pos[0]
            y = cur_pos[1]

        else:
            x = px
            y = py
            sx, sy = cfg.fix_pos
            dx = x - sx 
            dy = y - sy
            
        self.last_dxdy = (dx,dy)
        
        self.lastxy = (x, y)        
        cfg.last_xy_float = (x,y)
        self.last_cur_pos = cur_pos

        cfg.w2_last_move = (dx,dy)
        ll = math.sqrt(dx*dx+dy*dy)
        
        if round(dx) == 0 and round(dy) == 0:
            return
        if time.time()-cfg.clear_time2<0.03:
            return

        step = max(1, math.ceil(min_d / ll))
        if is_sca() and cfg.du_step==0:
            cfg.du_step = step
        if is_sca() and cfg.du_step!=0:
            step = cfg.du_step
        st = step
        min_idx = step
        for i in range(step,max_l, step):
            if i * ll > min_d_mouse:
                min_idx = i
                break
            
        if not cfg.isShow:
            st = min_idx
       
        if self.is_scal:
            rr = [0] + list(range(st, max_l, step))
        else:
            rr =  range(st, max_l, step)

        max_ll = 0        
        d1,d2 = get_last_idx((x,y,dx,dy))

        for i in rr:            
            zx = round(dx * i + x)
            zy = round(dy * i + y)          
            self.showl.append((str(i), zx, zy))
            max_ll = max(max_ll,i)            
            gg = max_zi
            if not cfg.isShow:
                gg = 1
                if self.is_scal:
                    gg = 2
                
            if len(self.showl) >= max_zi:
                break

            if not cfg.isShow:
                if cfg.fix_scroll != 0:                            
                    # 如果是相对偏移，加上cfg.maxi 即可
                    if len(self.showl)>=gg and i >= cfg.fix_scroll:                        
                        break

                elif cfg.manu_add!=0:
                    if len(self.showl)>=gg and len(self.showl) >= len(cfg.w2snap)+cfg.manu_add:                        
                        break

                elif self.to_is_changing:                    
                    if len(self.showl)>=gg and i*ll>= cfg.to:
                        break                    
                else:
                    if self.needBreak(i, ll, gg):
                        break                    

                
            else:
                if len(self.showl)>=gg:
                    break
            if d2>0 and i>=d2:
                break
            if i * ll > max_l:
                break        
        if not self.to_is_changing or cfg.fix_scroll != 0 or cfg.manu_add != 0:                            
            cfg.to = max(0,max_ll*ll-5)
            if cfg.manu_add > 0 and cfg.to>min_d*2:
                cfg.to = max_ll*ll- min_d*0.9
            
        if cfg.fix_scroll != 0 or cfg.manu_add !=0:
            if cfg.min_ge_force_show:
                cfg.min_ge = 0
            set_to_chg()
            print('set to time')
            self.to_is_changing = True                    
        
        if not self.is_scal:
            cfg.last_ge = len(self.showl)
        else:
            cfg.last_ge = len(self.showl) -1                    

        if not self.is_scal:
            return
        
        self.sca_c_show = True
        self.fix_c_show = True
        cfg.has_show_sca = True
       
        self.fix_c.draw(sx, sy)
        self.sca_c.draw(cfg.sca_cur_pos[0], cfg.sca_cur_pos[1])
            